using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.ArchitectureTools.CodeRepositoryQuery;
using UCL.Powersource.Analysis;
using UCL.Powersource.TFS;

using System.Runtime.Serialization;
using System.Diagnostics.CodeAnalysis;

namespace UCL.Powersource.Statistics
{
    /// <summary>
    /// Class for calculation of the number of classes defined in the indexed assembliesd
    /// </summary>
    [Export(typeof(IStatistic))]
    [DataContract(IsReference = true)]
    public class NumberOfClassesStats : StatisticTeamBase
    {
        /// <summary>
        /// Class for statistics calculation
        /// </summary>
        /// <param name="teamProjConfig">Tfs stat project collection configuration</param>
        /// <param name="timeFrame">Work item frame</param>
        /// <returns>Number of statistics</returns>
        protected override double? CalculateFor(ITfsTeamProjectConfiguration teamProjConfig, ITimeFrame timeFrame)
        {
            int definedClassesCount = 0;

            var analysisBridge = teamProjConfig.ProjectAnalysisBridge;
            var codeIndex = analysisBridge.RetrieveCodeIndex(timeFrame); 

            // We won't modify the code index.
            codeIndex.Assemblies.MergeOption =         System.Data.Objects.MergeOption.NoTracking;
            codeIndex.AssemblyReferences.MergeOption = System.Data.Objects.MergeOption.NoTracking;
            codeIndex.Namespaces.MergeOption =         System.Data.Objects.MergeOption.NoTracking;
            codeIndex.Types.MergeOption =              System.Data.Objects.MergeOption.NoTracking;
            codeIndex.TypeDefinitions.MergeOption =    System.Data.Objects.MergeOption.NoTracking;
            codeIndex.MethodDefinitions.MergeOption =  System.Data.Objects.MergeOption.NoTracking;
            codeIndex.Fields.MergeOption =             System.Data.Objects.MergeOption.NoTracking;
            codeIndex.Properties.MergeOption =         System.Data.Objects.MergeOption.NoTracking;
            codeIndex.Events.MergeOption =             System.Data.Objects.MergeOption.NoTracking;

            // Number of types defined in the indexed assemblies. 
            // We exclude the compiler generated types.
            IQueryable<TypeDefinition> definedTypes =
                codeIndex.TypeDefinitions.Where(t => !t.IsRuntimeSpecialName && !t.IsToolSpecialName);

            // We get the number of classes
            definedClassesCount = definedTypes.Count(t => t.KindAsShort == (short)TypeKind.Class);

            return definedClassesCount;
        }

        [ExcludeFromCodeCoverage]
        public override string Label
        {
            get { return "Number of classes"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Description
        {
            get { return "Number of classes defined in the indexed assemblies"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Name
        {
            get { return "NumberOfClassesStats"; }
        }

        public static readonly Guid CN_Statistic_Guid = new Guid("3D3C1202-0237-4911-9BC3-08C0C60E5938");
       [ExcludeFromCodeCoverage]
        public override Guid Statistic_Guid
        {
            get { return CN_Statistic_Guid; }
        }

        [DataMember]
        private string _FormatString = "0";

        public override string FormatString
        {
            get
            {
                return _FormatString;
            }
        }

        public override bool RequiresBuild
        {
            get { return true; }
        }
    }
}
